﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 多线程
{
    public class BarrierDemo
    {
        /*
         * 使多个任务能够采用并行方式依据某种算法在多个阶段中协同工作。
         * 
         * barrier 跟其他信号有点不同 
         * barrier 是子线程执行到某一步时阻塞子线程等待其他线程当其他线程也达到信号点时再一起执行
         * 
         * 
         */

        /*
                并行线程0
                并行线程1
                并行线程2
                并行线程3
                并行线程4
                0--并行线程0到达信号点，开始等待
                0--并行线程2到达信号点，开始等待
                0--并行线程3到达信号点，开始等待
                0--并行线程1到达信号点，开始等待
                0--并行线程4到达信号点，开始等待
                并行线程4,继续执行
                并行线程0,继续执行
                并行线程2,继续执行
                并行线程3,继续执行
                并行线程1,继续执行
                线程4执行完成
                线程3执行完成
                线程1执行完成
                线程2执行完成
                线程0执行完成


                并行线程总数5
                并行线程2
                并行线程0
                并行线程1
                0--并行线程2到达信号点，开始等待
                并行线程4
                并行线程3
                0--并行线程0到达信号点，开始等待
                0--并行线程3到达信号点，开始等待
                0--并行线程4到达信号点，开始等待
                0--并行线程1到达信号点，开始等待
                并行线程1,继续执行
                并行线程0,继续执行
                并行线程3,继续执行
                1--并行线程1到达信号点，开始等待
                1--并行线程0到达信号点，开始等待
                1--并行线程3到达信号点，开始等待
                并行线程2,继续执行
                并行线程4,继续执行
                1--并行线程2到达信号点，开始等待
                1--并行线程4到达信号点，开始等待
                并行线程4,继续执行
                并行线程3,继续执行
                并行线程1,继续执行
                并行线程0,继续执行
                并行线程2,继续执行
                2--并行线程4到达信号点，开始等待
                2--并行线程3到达信号点，开始等待
                2--并行线程1到达信号点，开始等待
                2--并行线程0到达信号点，开始等待
                2--并行线程2到达信号点，开始等待
                并行线程2,继续执行
                并行线程4,继续执行
                并行线程3,继续执行
                并行线程0,继续执行
                并行线程1,继续执行
                线程2执行完成
                线程4执行完成
                线程3执行完成
                线程0执行完成
                线程1执行完成

         */

        private static void Main1()
        {
            Task[] tasks = new Task[5];
            Barrier barrier = new Barrier(5);

            Console.WriteLine($"并行线程总数{barrier.ParticipantCount}");
            Parallel.For(0, 5, (i) =>
            {
                tasks[i] = Task.Run(() =>
                {

                    System.Console.WriteLine($"并行线程{i}");
                    for (int j = 0; j < 1000000; j++)
                    {
                        if (j == 1000000 / 10)
                        {
                            Console.WriteLine($"阶段{barrier.CurrentPhaseNumber}--并行线程{i}到达信号点，开始等待");

                            barrier.SignalAndWait();

                            Console.WriteLine($"并行线程{i},继续执行");
                        }
                        if (j == 1000000 / 8)
                        {
                            Console.WriteLine($"阶段{barrier.CurrentPhaseNumber}--并行线程{i}到达信号点，开始等待");

                            barrier.SignalAndWait();

                            Console.WriteLine($"并行线程{i},继续执行");
                        }

                        if (j == 1000000 / 5)
                        {
                            Console.WriteLine($"阶段{barrier.CurrentPhaseNumber}--并行线程{i}到达信号点，开始等待");

                            barrier.SignalAndWait();
                           
                            Console.WriteLine($"并行线程{i},继续执行");
                        }
                        if (j == 1000000 / 4)
                        {
                            Console.WriteLine($"阶段{barrier.CurrentPhaseNumber}--并行线程{i}到达信号点，开始等待");

                            barrier.SignalAndWait();

                            Console.WriteLine($"并行线程{i},继续执行");
                        }
                        if (j == 1000000 / 2)
                        {
                            Console.WriteLine($"阶段{barrier.CurrentPhaseNumber}--并行线程{i}到达信号点，开始等待");

                            barrier.SignalAndWait();

                            Console.WriteLine($"并行线程{i},继续执行");
                        }

                    }
                    
                });
                tasks[i].Wait();
                Console.WriteLine($"线程{i}执行完成");
            });


        }
    }
}
